package org.zh.client.config;

import com.fasterxml.jackson.core.type.TypeReference;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.zh.client.cache.RemoteCache;
import org.zh.entity.MethodBean;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.Charset;
import java.util.List;

import static org.zh.client.config.GlobalStatic.GLOBAL_TRANSACTION;
import static org.zh.client.config.GlobalStatic.GLOBAL_ThreadLocal;
import static org.zh.util.CommonStatic.*;
import static org.zh.util.CommonStatic.om;

@Configuration
public class ClientConfig  {
  @Bean
    public WebFilter filter(){
      return (ServerWebExchange exchange, WebFilterChain chain)->{
          List<String> strings = exchange.getRequest().getHeaders().get(GLOBAL_TRANSACTION);
          if (strings != null && StringUtils.hasLength(strings.getFirst())) {
              GLOBAL_ThreadLocal.set(strings.getFirst());
          }
          return chain.filter(exchange).doFinally(
                  s -> {
                      if (GLOBAL_ThreadLocal.get() != null) {
                          GLOBAL_ThreadLocal.remove();
                      }
                  }
          );
      };
    }
    @Bean
    public MethodInterceptor getMethodInterceptor() {
        return inv -> {
            Method method = inv.getMethod();
            Class<?> ainterface = method.getDeclaringClass();
            Object[] args = inv.getArguments();
            Object result = "";
            if (args.length > 0) {
                if (args.length == 1) {
                    result = args[0];
                }
                if (args.length > 1) {
                    result = args;
                }
            }
            // 从缓存中获取服务信息
            MethodBean methodBean = RemoteCache.loadBalancingOne(ainterface.getName(), method.getName());
            HttpRequest.Builder builder = HttpRequest.newBuilder()
                    .uri(URI.create(methodBean.completeUrl()))
                    .method(methodBean.requestMethod(), HttpRequest.BodyPublishers.ofString(om.writeValueAsString(result)))
                    .header(http_ContentType, http_json)
                    .header(http_Accept, http_json)
                    .header(http_AcceptCharset, Charset.defaultCharset().name());
            String gt = GLOBAL_ThreadLocal.get();
            if (gt != null) {
                builder.header(GLOBAL_TRANSACTION, gt);
            }
            HttpRequest request = builder.build();
            HttpResponse<String> response = httpClient_1_1.send(request, HttpResponse.BodyHandlers.ofString());
            int statusCode = response.statusCode();
            if (statusCode != 200) {
                throw new RuntimeException("Unexpected response status: " + statusCode + "::" + methodBean.completeUrl());
            }
            return om.readValue(response.body(), new TypeReference<>() {
                public Type getType() {
                  return method.getGenericReturnType();
                }
            });
        };
    }



}
